package org.itboys.core.service.mysql.front;

import org.apache.commons.lang3.StringUtils;
import org.itboys.commons.ErrorException;
import org.itboys.commons.utils.tools.ListUtil;
import org.itboys.core.common.ExceptionEnum;
import org.itboys.core.common.SundayCommonConstants;
import org.itboys.core.common.WalletRecordEnum;
import org.itboys.core.dao.pay.SundayPayConfigMapper;
import org.itboys.core.dao.wallet.SundayWalletRecordMapper;
import org.itboys.core.dto.pay.SundayPayDto;
import org.itboys.core.entity.mysql.pay.SundayPay;
import org.itboys.core.entity.mysql.pay.SundayPayConfig;
import org.itboys.core.entity.mysql.wallet.record.SundayWalletRecord;
import org.itboys.core.entity.mysql.wallet.record.SundayWalletRecordExample;
import org.itboys.core.util.NumberUtil;
import org.itboys.mysql.service.BaseMySqlService;
import org.itboys.pay.alipay.AlipayMobileService;
import org.itboys.pay.alipay.AlipayWapResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
*@Author: jiaqilei
*@Date: 19:28 2018/11/28
*@Discription: 支付
*/
@Service
public class SundayFrontPayService extends BaseMySqlService<SundayPay> {
    public static String PAY_CALLBACK_URL_alipay = "http://tray.vipgz1.idcfengye.com/sunday/mobile/pay/callback/alipay";
    //public static String PAY_CALLBACK_URL_alipay = "http://mobile.palletto.cn//sunday/mobile/pay/callback/alipay";
    @Autowired
    private SundayWalletRecordMapper recordMapper;
    @Autowired
    private SundayPayConfigMapper payConfigMapper;
    @Autowired
    private SundayFrontWalletService walletService;

    /**
     * 预支付
     * @param recordIds
     * @return
     */
    @Transactional
    public SundayPayDto preparePay(List<Long> recordIds) {
        //1,声明返回结果
        SundayPayDto payDto;
        //传入第三方的外部订单号
        String orderNo = NumberUtil.generateNumber("PREPAY");
        //支付描述
        String remark = WalletRecordEnum.CHONGZHI.getDesc();
        //本次需要支付的金额
        BigDecimal payAmount =BigDecimal.ZERO;
        //本次需要操作的订单（余额充值记录）ids
        StringBuilder orderIdsStr = new StringBuilder();
        SundayWalletRecordExample example=new SundayWalletRecordExample();
        example.createCriteria()
                .andIdIn(recordIds)
                .andIsDeletedEqualTo(SundayCommonConstants.NO);
        List<SundayWalletRecord> records = recordMapper.selectByExample(example);
        for (SundayWalletRecord record : records) {
            if(record.getType().equals(WalletRecordEnum.CHONGZHI.getCode())){
                payAmount=payAmount.add(record.getMoney());
            }
            //存放需要充值记录ID时，用_隔开;
            orderIdsStr.append(record.getId() + "_");
        }
        //4，返回移动端需要的支付参数
        Map<String,Object> param=new HashMap<>();
        SundayPayConfig payConfig = null;
        List<SundayPayConfig> payConfigs = payConfigMapper.select(param);
        //4.1,返回支付宝参数
            for (SundayPayConfig p : payConfigs) {
                if ( SundayCommonConstants.pay_type_alipay.equals(p.getType())) {
                    payConfig = p;
                }
            }
            if (payConfig == null) {
                throw new ErrorException(ExceptionEnum.ZFB_NO_CONFIG_EXCEPTION.getValue());
            }
            String alipayResult = null;
            try {
                //获取平台的支付宝PID
                //商户私钥
                String alipayAppPrivatekey = payConfig.getAlipayAppPrivateKey();
                logger.info("--支付宝商户私钥--" + alipayAppPrivatekey);
                //商户公钥
                String alipayAppPublicKey = payConfig.getAlipayAppPublicKey();
                logger.info("--支付宝商户公钥--" + alipayAppPublicKey);
                alipayResult = AlipayMobileService.newAppPay(
                        payConfig.getAlipayAppId(), payAmount.toString(), orderNo,
                        PAY_CALLBACK_URL_alipay, alipayAppPrivatekey,
                        remark, remark, alipayAppPublicKey);
            } catch (Exception e) {
                logger.info("预支付，支付宝，内部组装参数错误");
                e.printStackTrace();
                throw new ErrorException(ExceptionEnum.ZFB_PAY_EXCEPTION.getValue());
            }
            payDto = new SundayPayDto(orderNo, payAmount.toString(), remark, alipayResult);


        logger.info("orderIdsStr--=" + orderIdsStr);
        //5，本地存储预支付的结果，便于第三方支付回掉时执行业务逻辑
        SundayPay pay = new SundayPay(orderNo, orderIdsStr.substring(0, orderIdsStr.length() - 1).toString(),
                payAmount.setScale(2, BigDecimal.ROUND_HALF_UP), WalletRecordEnum.CHONGZHI.getCode(), remark);
        super.insert(pay);
        return payDto;
    }


    /**
     * 支付宝支付回调
     *
     * @param request
     * @param
     */
    @Transactional
    public AlipayWapResult callback_alipay(HttpServletRequest request) {
        AlipayWapResult alipayWapResult = new AlipayWapResult();
        //1，检验签名和请求来源
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("type", SundayCommonConstants.pay_type_alipay);
        List<SundayPayConfig> payConfigs = payConfigMapper.select(param);
        //支付宝公钥
        String publicKey = "";
        if (ListUtil.isNull(payConfigs)) {
            return alipayWapResult;
        }
        //支付宝公钥
        publicKey = payConfigs.get(0).getAlipayPublicKey();
        logger.info("--支付宝公钥--" + publicKey);
        try {
            alipayWapResult = AlipayMobileService.notifyResult(request, publicKey);
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("支付-支付宝-回掉-签名验证错误。" + e);
            return alipayWapResult;
        }
        //验证成功或失败的标识
        boolean verify_result = alipayWapResult.isVerify_result();

        String trade_status = alipayWapResult.getTrade_status();
        String out_trade_no = alipayWapResult.getOut_trade_no();
        String trade_no = alipayWapResult.getTrade_no();
        String notify_data = alipayWapResult.getNotify_data();
        BigDecimal price = alipayWapResult.getPrice();
        logger.info("支付-支付宝-回掉-信息.trade_status=" + trade_status +
                ",out_trade_no=" + out_trade_no +
                ",trade_no=" + trade_no +
                ",notify_data=" + notify_data +
                ",price=" + price +
                ",verify_result=" + verify_result);
        if (!verify_result) {
            logger.error("支付-支付宝-回掉-签名验证失败。");
            return alipayWapResult;
        }

        //查询本地预支付记录
        param.clear();
        if (StringUtils.isEmpty(out_trade_no)) {
            logger.error("支付-支付宝-open-回掉-外部订单为空");
            alipayWapResult.setVerify_result(false);
            return alipayWapResult;
        }
        param.put("orderNo", out_trade_no);
        List<SundayPay> pays = super.select(param);
        if (ListUtil.isNull(pays)) {
            logger.error("支付-支付宝-回掉-本地无预支付记录，返回");

            alipayWapResult.setVerify_result(false);
            return alipayWapResult;
        }
        SundayPay pay = pays.get(0);
        //2，项目内部逻辑。校验支付金额

        if (WalletRecordEnum.CHONGZHI.getCode().equals(pay.getType())) {
            List<Long> recordIds = new ArrayList<Long>();
            for (String incomeRecordIdStr : pay.getOrderIds().split("_")) {
                recordIds.add(Long.valueOf(incomeRecordIdStr));
            }
            if (ListUtil.isNull(recordIds)) {
                logger.error("支付-支付宝-回掉-本地预支付记录无充值记录参数，返回");
                alipayWapResult.setVerify_result(false);
                return alipayWapResult;
            }
            param.clear();
            param.put("status", 0);
            param.put("ids", recordIds);
            SundayWalletRecordExample example=new SundayWalletRecordExample();
            example.createCriteria()
                    .andIsDeletedEqualTo(SundayCommonConstants.NO)
                    .andIdIn(recordIds)
                    .andStatusEqualTo(SundayCommonConstants.NO);
            List<SundayWalletRecord> records = recordMapper.selectByExample(example);

            for (SundayWalletRecord record : records) {
                if (WalletRecordEnum.CHONGZHI.getCode() .equals(record.getType())&&
                        record.getMoney().compareTo(price) == 1) {
                    logger.error("支付-支付宝-回掉-余额充值实际支付金额错误，应支付金额=" + record.getMoney() +
                            "，实际支付金额=" + price + "，充值记录ID=" + record.getId() + ",预支付订单编号=" + out_trade_no);
                    alipayWapResult.setVerify_result(false);
                    return alipayWapResult;
                }
                walletService.chargeBack(record);
            }
        }

        alipayWapResult.setVerify_result(verify_result);
        return alipayWapResult;
    }
}
